# coding=utf-8
import datetime
import json
import os
import threading
import time

import xlrd
from PyQt5 import QtCore
# pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install pyqt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install PyQtWebEngine -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install pynput -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install pyautogui -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install time -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
# pip install yaml -i https://pypi.tuna.tsinghua.edu.cn/simple
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, \
    QHBoxLayout, QTableWidget, QTableWidgetItem, QFileDialog, QMessageBox, \
    QMenu

from common.tools import get_project_path, sep
from logs.log import get_log
from ui.BaseWin import BaseWin
from ui.message_tip import MessageTip
from ui.result_ui import ResultUi

log = get_log("TableUi")


class TableUi(BaseWin):
    switch_win = QtCore.pyqtSignal()
    detail_switch_win = QtCore.pyqtSignal(object)

    def __init__(self, app, config):
        super(TableUi, self).__init__(app)
        self.config = config
        # self.setWindowTitle("我是子窗口啊")
        self.init_ui()
        # self.setWindowFlag(QtCore.Qt.WindowType.WindowStaysOnTopHint, True)

    def create_table(self):
        self.table = QTableWidget()
        heads = self.config['heads']
        self.table.setRowCount(0)
        self.table.setColumnCount(len(heads))

        self.table.verticalHeader().setVisible(False)  # 去掉行号
        self.table.resizeColumnsToContents()  # 设置表格自动列宽
        header = self.table.horizontalHeader()
        header.setStyleSheet(
            "QHeaderView::section {background-color: rgb(26, 182, 255); color: white;} ")  # 设置表头颜色为红色，字体颜色为白色
        self.table.setShowGrid(True)

        log.info(self.config)
        self.table.setHorizontalHeaderLabels(heads)

        for j in range(len(heads)):
            self.table.setColumnWidth(j, 100)

        self.table.cellChanged.connect(self.printTable)
        # self.table.cellDoubleClicked.connect(self.del_func)
        self.table.setAlternatingRowColors(True)  # 隔行变色设置

        # 打开 右键菜单 设置
        self.table.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)  # 允许右键产生子菜单
        self.table.customContextMenuRequested.connect(self.sonsTableGenerateMenu)  # 联接右键菜单

        return self.table

    def sonsTableGenerateMenu(self, pos):
        # print( pos)
        menu = QMenu()
        item1 = menu.addAction(u"添加行")
        item2 = menu.addAction(u"删除行")
        action = menu.exec_(self.table.mapToGlobal(pos))  # 窗口坐标系转换为屏幕坐标系
        if action == item1:
            self.add_func()
        elif action == item2:
            self.del_func()
        else:
            pass

    def printTable(self):
        log.info("printTable")

    def init_ui(self):
        self.setWindowTitle("运行参数")
        # 创建布局
        layout = QVBoxLayout()

        # 创建QListWidget组件

        hbox1 = QHBoxLayout()

        self.back_button = QPushButton('返回', self)
        self.back_button.setCheckable(True)  # 1
        self.back_button.toggled.connect(self.back_func)
        hbox1.addWidget(self.back_button)

        self.clear_button = QPushButton('清空', self)
        self.clear_button.setCheckable(True)  # 1
        self.clear_button.toggled.connect(self.clear_func)
        hbox1.addWidget(self.clear_button)

        self.add_button = QPushButton('添加行', self)
        self.add_button.setCheckable(True)  # 1
        self.add_button.toggled.connect(self.add_func)
        hbox1.addWidget(self.add_button)

        self.upload_button = QPushButton('导入数据', self)
        self.upload_button.setCheckable(True)  # 1
        self.upload_button.clicked.connect(self.getfile)
        hbox1.addWidget(self.upload_button)

        self.confirm_button = QPushButton('确认执行', self)
        self.confirm_button.setCheckable(True)  # 1
        self.confirm_button.toggled.connect(self.confirm_func)
        hbox1.addWidget(self.confirm_button)

        self.detail_button = QPushButton('执行记录', self)
        self.detail_button.setCheckable(True)  # 1
        self.detail_button.toggled.connect(self.detail_func)
        hbox1.addWidget(self.detail_button)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(self.create_table())

        layout.addLayout(hbox1, 3)
        layout.addLayout(hbox2, 7)
        # 将网格布局应用到当前窗口
        self.setLayout(layout)
        self.set_center()

    def getfile(self):
        fname = QFileDialog.getOpenFileName(self, '选择文件', '/', 'excel(*.xls *.xlsx)')
        if not fname or len(fname) == 0 or not fname[0]:
            return
        log.info(fname[0])
        try:
            readfile = xlrd.open_workbook(fname[0])
            names = readfile.sheet_names()
            if names and len(names) > 0:
                print(names)
                for name in names:
                    log.info(name)
                    obj_sheet = readfile.sheet_by_name(name)
                    row = obj_sheet.nrows
                    # 获取sheet列数
                    col = obj_sheet.ncols
                    # 获取 单元格数据
                    heads = []
                    list = []
                    for i in range(row):
                        data = {}
                        for j in range(col):
                            ctype = obj_sheet.cell(i, j).ctype  # 表格的数据类型
                            cell = obj_sheet.cell_value(i, j)
                            if cell and ctype == 2 and cell % 1 == 0.0:  # ctype为2且为浮点
                                cell = int(cell)  # 浮点转成整型
                            if i == 0:
                                heads.append(cell)
                            else:
                                data[heads[j]] = str(cell)
                        if i != 0:
                            list.append(data)
                    self.import_data(list)
        except Exception as e:
            log.error(str(e))
            QMessageBox.critical(self, "提示", str(e))

    def import_data(self, list):
        if not list or len(list) == 0:
            return
        heads = self.config['heads']
        row_count = self.table.rowCount()
        self.table.setRowCount(row_count + len(list))
        for i in range(len(list)):
            data = list[i]
            for j in range(len(heads)):
                item = QTableWidgetItem()
                if heads[j] in data:
                    item.setText(data[heads[j]])
                else:
                    item.setText("")
                self.table.setItem(row_count + i, j, item)

    def get_table_data(self):
        row_count = self.table.rowCount()
        heads = self.config['heads']
        list = []
        for i in range(row_count):
            data = {}
            for j in range(len(heads)):
                head = heads[j]
                input = self.table.item(i, j)
                if input:
                    data[head] = self.table.item(i, j).text()
                else:
                    data[head] = ""

            list.append(data)
        log.info(list)
        return list

    def confirm_func(self):
        if self.confirm_button.isChecked() == False:
            return
        self.confirm_button.setChecked(False)
        pro = self.config
        tip = MessageTip(self.app, f"{pro['title']}执行中")

        def my_thread():
            result = None
            start_time = time.time()
            try:
                log.info(pro)
                # eval(pro['eval'])
                module_name = __import__(pro['module'])
                function = getattr(module_name, pro['method'])
                result = function(self.get_table_data())
                execution_time = time.time() - start_time
                log.info(f"执行成功:{pro['module']}-{pro['method']}，用时：{execution_time}MS")
                self.write_result(result, True, None, execution_time)
                ResultUi(self.app, result).exec()
            except BaseException as e:  # 未捕获到异常，程序直接报错
                log.error(str(e))
                execution_time = time.time() - start_time
                log.warn(f"执行失败:{pro['module']}-{pro['method']}，用时：{execution_time}MS")
                self.write_result(result, False, e, execution_time)
                # QMessageBox.critical(self, "提示", str(e))
            finally:
                tip.close()
                pass

        thread = threading.Thread(target=my_thread)
        thread.start()
        tip.exec()

    def write_result(self, data, success=True, error=None, exe_time=0):
        if not success:
            for item in data:
                if hasattr(item, 'success'):
                    item['success'] = False
                    item['message'] = str(error)
        date_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        dir_path = get_project_path() + ('/'.join(["temp", "result", str(date_time)]))
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        map = {'success': success, "error": error, 'list': data, 'config': self.config, 'time': date_time,
               'use_time': exe_time}
        write_str = json.dumps(map, ensure_ascii=False, indent=4)
        with open(os.path.join(dir_path, 'data.json'), 'w') as file:
            file.write(write_str)

    def closeEvent(self, event):
        # self.switch_win.emit()
        pass

    def add_func(self):
        if self.add_button.isChecked():
            self.add_button.setChecked(False)
            row_count = self.table.rowCount()
            self.table.setRowCount(row_count + 1)

    def del_func(self):
        current_index = self.table.currentRow()  # 获取当前行号
        self.table.removeRow(current_index)

    def back_func(self):
        self.switch_win.emit()
        self.close()

    def clear_func(self):
        if self.clear_button.isChecked():
            self.clear_button.setChecked(False)
            self.table.setRowCount(0)

    def detail_func(self):
        print("33")
        self.detail_switch_win.emit(self.config)
        print("44")
        self.close()
